Skip to content

feat(dialog): add default_suffix to the save-file picker#138

Merged
pabloinigoblasco merged 2 commits into
feature/plot-markersfrom
feat/dialog-save-file-picker
Jun 29, 2026
Merged

feat(dialog): add default_suffix to the save-file picker#138
pabloinigoblasco merged 2 commits into
feature/plot-markersfrom
feat/dialog-save-file-picker

Conversation

@pabloinigoblasco

@pabloinigoblasco pabloinigoblasco commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Builds on PlotJuggler/plotjuggler_sdk#135 (which introduces the save-file picker as part of the pj.data_processors.v1 unification) and adds the optional default_suffix argument to setSaveFilePicker — appended to the typed filename when it carries no extension (so exporting library saves library.json).

Targeted at feature/plot-markers so the two merge cleanly: the picker's setter and isSaveFilePicker are identical to #135's; this branch's only delta is default_suffix plus its saveFilePickerDefaultSuffix accessor. Filter/title are read through the shared filePicker* accessors, matching #135's style.

Contents

  • WidgetData::setSaveFilePicker gains default_suffix = "" (writes e["default_suffix"]).
  • WidgetDataView::saveFilePickerDefaultSuffix.
  • docs: dialog-sdk-reference.md, dialog-plugin-guide.md.

Pairs with

The host rendering (PlotJuggler/PJ4#252) and the Transform Editor library Export that uses it (PlotJuggler/pj-official-plugins#158).

Add WidgetData::setSaveFilePicker and the matching WidgetDataView
accessors so a plugin can turn a button into a native "save as" chooser.
The chosen path is delivered through the existing onFileSelected handler,
so no new event type or typed handler is required. This is a
backward-compatible API addition, so bump the SDK to 0.13.0 and bring
recipe.yaml back in sync with the other version sources.

Contents:
- setSaveFilePicker(name, text, filter, title, default_suffix) -> "save_file_picker" action
- WidgetDataView: isSaveFilePicker / saveFilePickerFilter / Title / DefaultSuffix
- version 0.13.0 in conanfile.py, CMakeLists.txt, recipe.yaml + docstring example
- docs: dialog-sdk-reference.md and dialog-plugin-guide.md
The save-file picker now lives on top of the markers/data-processors
unification branch. setSaveFilePicker / isSaveFilePicker are taken from that
branch; this branch's only remaining contribution is the optional
default_suffix argument (and its saveFilePickerDefaultSuffix accessor),
appended to the typed name when it carries no extension. Filter/title are read
through the shared filePicker accessors, matching that branch's style.
@pabloinigoblasco pabloinigoblasco changed the title feat(dialog): add save-file picker to the dialog SDK feat(dialog): add default_suffix to the save-file picker Jun 28, 2026
@pabloinigoblasco pabloinigoblasco changed the base branch from main to feature/plot-markers June 28, 2026 20:30
@pabloinigoblasco pabloinigoblasco merged commit a3d1513 into feature/plot-markers Jun 29, 2026
6 of 7 checks passed
@pabloinigoblasco pabloinigoblasco deleted the feat/dialog-save-file-picker branch June 29, 2026 06:56
Alvvalencia added a commit that referenced this pull request Jun 29, 2026
…ta_processors.v1 (kind discriminator) (#135)

* Add PlotMarkers canonical builtin object + codec (markers Phase 1)

New SDK builtin type for time-series plot markers (findings), the
foundation of the anomaly-detection pipeline feature.

- PlotMarkers (kPlotMarkers = 18): homogeneous, id-less marker records
  (Region / Event / ValueBand / Label) with shared semantic fields
  (status, severity, category, label, description, color, metadata) +
  a PlotMarkers list container. No id/source/scope by design — identity
  is owned by the host marker store; location carries provenance/reach.
- Hand-written PJ.PlotMarkers wire codec following the
  image_annotations_codec idiom; PlotMarkers.proto contract.
- Registered in C++ + C-ABI builtin enums, name()/parse()/typeOf(), and
  the ABI layout sentinel (static_assert id == 18).
- Round-trip codec tests; full pj_base suite green (32/32) under ASAN.
- Design (use-cases, architecture) + wire-format docs.

ColorRGBA reused via image_annotations.hpp per the existing house
convention (mesh3d / scene_entities do the same).

abi/baseline.abi refresh + SDK MINOR version bump deferred to the
release-cut step (additions-only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add pj.marker_store.v1 C-ABI service (create/delete/query markers)

The plugin-facing contract for plot markers, mirroring the object
read/write host pattern.

- C vtable PJ_marker_store_host_vtable_t + fat pointer + an owning
  PJ_marker_query_handle_t (plugin_data_api.h): add / remove / query /
  query_bytes / release_query. Markers cross as serialized PJ.PlotMarkers
  bytes; ids cross as uint64.
- C++ MarkerStoreHostView (plugin_data_api.hpp) wrapping the codec so
  callers work in typed sdk::PlotMarker; add(single|batch) -> ids,
  remove(id), query -> [{id, marker}]. + MarkerEntry.
- MarkerStoreService trait (service_traits.hpp), "pj.marker_store.v1".

ABI is additive (new service); abi/baseline.abi refresh deferred to the
release-cut step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* markers: drop pj.marker_store.v1 service; add object-on-dataset toolbox slot

Markers become a builtin object published to the ObjectStore via the generic object-write surface; the producer republishes the whole PlotMarkers set (last-writer-publish). The dedicated pj.marker_store.v1 service (vtable, MarkerStoreHostView, service trait) is removed.

Add a tail-appended, idempotent toolbox-host slot register_object_topic_on_dataset(DatasetId, ...) so a toolbox can annotate an existing dataset (the object-write path was previously source-scoped). Add marker object-topic naming helpers (markerObjectTopicName / kGlobalMarkerTopic) to plot_markers.hpp. Update the ABI layout sentinel (88->96) and the two mock vtables.

The PlotMarkers type + codec are unchanged. Docs (plot_markers_*) updated to the ObjectStore + republish model. MINOR bump + abi/baseline.abi refresh deferred to release.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* markers: MarkerTimeline dialog widget + dataset-scoped read & object-retention toolbox ABI slots

Dialog protocol: add the MarkerTimeline custom widget (TimelineMark setters/event/parser/callback) for an editable multi-marker strip, with a single shared TimelineMark<->JSON codec used by all four sites.

Toolbox host ABI (tail-appended, struct_size-gated): lookup_topic_on_dataset on the object-read vtable (dataset-scoped topic resolution; the name-only lookup is ambiguous across datasets) and set_object_topic_retention on the write vtable (keep-latest-N so a republishing producer's snapshots don't accumulate). Toolbox-host vtable 96->104; sentinels + mock vtables updated.

Add sdk::markerSeriesKey (single-slash join tolerating a leading-'/' field) so producer and overlay build the per-series key identically. Doc refresh.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(dialog): save-as file picker + chart-marker overlay; codec cleanup

Additive dialog-protocol surface (ABI-safe, no version bump):
- setSaveFilePicker / isSaveFilePicker — a native "Save As" picker (getSaveFileName)
  so a not-yet-existing file can be created; reported via the existing onFileSelected.
- ChartMarker + setChartMarkers / chartMarkers — overlay markers (events/regions/
  value-bands) on a chart preview, alongside setChartSeries.
- Fix a stale comment that referenced QLineSeries (the preview is Qwt, not Qt Charts).

Cleanup: decodeMarker now drives the shared builtin_wire::parseFields loop like the
sibling codecs, replacing the hand-rolled continue/break/skip control flow. Behavior
and wire format are unchanged (codec round-trip tests pass).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RcygzPWUrHf9jHGGwzEzZo

* chore(sdk): bump to 0.12.0 (PlotMarkers builtin on top of merged 0.11.0)

Adding the PlotMarkers canonical builtin (slot 19) is a MINOR addition over
main's 0.11.0, so the merged SDK is a distinct 0.12.0 — not the upstream 0.11.0
(which lacks PlotMarkers). Keeps version identity clean for downstream pins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BeoYQHmF6ixvYv9KXXgyVh

* feat(pj_base): add pj.markers.v1 host service (whole-series markers + ephemeral preview)

The whole-series analog of pj.data_processors.v1: a plugin submits a marker
generator by data (script + input series + an output marker-topic + params) and
the HOST runs it over the whole series and publishes the resulting PlotMarkers to
the ObjectStore. Nothing executable crosses the boundary.

- PJ_markers_host_vtable_t (plugin_data_api.h): create/remove/list/config +
  tail-appended set_marker_preview / clear_marker_preview for a live, ephemeral
  (non-persisted) preview generator read back through the object surface.
- MarkersHostView (sdk/plugin_data_api.hpp) + MarkersHostService trait.
- params_json {"scope":"all"} makes a global generator publish across every
  dataset; absent = the active dataset only.
- markers_api_test.cpp: fake-host ABI test (forwarding, count-then-fill,
  borrowed-string lifetime, binary-safe payload, preview slots).

Single output_marker_topic (not an outputs[] array): a generator writes exactly
one marker topic (global or per-series).

NOTE: MINOR version bump (conanfile.py / PJ_PACKAGE_VERSION / recipe.yaml) and the
abidiff baseline refresh are pending pre-merge — this commit adds API on a feature
branch (WIP) and does not bump the release version yet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsY1SE2yBsX2qXvkgEnX8U

* feat(sdk)!: replace pj.markers.v1 with unified pj.generators.v1 service

Unify the whole-series host-driven service under one SDK contract,
PJ_generators_host_vtable_t / GeneratorsHostService ("pj.generators.v1"),
with a string `kind` discriminator:

- kind="markers" (objects -> ObjectStore) is implemented; shared `language`
  param, compile-only validate_script, ephemeral-preview flag, and out_topics
  return apply across kinds.
- kind="transform" (per-sample timeseries -> DerivedEngine) is RESERVED, not
  implemented; its end-state home is decided when the transform-editor work merges.

Removes PJ_markers_host_vtable_t / MarkersHostService (the old pj.markers.v1) and
markers_api_test; adds generators_api_test. A speculative kind="field" that briefly
existed on this branch was dropped (zero consumers, violated the object/timeseries
engine split); it changed no ABI struct since `kind` is a runtime string.

Versioning: API removal, normally MAJOR. Ships as 0.13.0 because no public tag ever
carried pj.markers.v1 (no released plugin breaks). The first public release carrying
pj.generators.v1 MUST be tagged 1.0.0 -- recorded in CHANGELOG.md + a comment by
`version` in conanfile.py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013N1nzqco4Y9AQhnQgXo5tQ

* style(sdk): clang-format the unified data-processors API surface

Applies the pre-commit clang-format pass that the merge commit (bf7eb0f) skipped
via --no-verify. Formatting only — no semantic change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHPK8VduUcoenjL8AtoSVd

* style(sdk): clang-format remaining branch files (proto + dialog typed)

Completes the formatting pass over the full PR diff (PlotMarkers.proto column
alignment + dialog_plugin_typed.hpp signature wrap) that the narrowly-scoped
previous pass missed. Formatting only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHPK8VduUcoenjL8AtoSVd

* feat(dialog): add save-file picker to the dialog SDK (#138)

Add WidgetData::setSaveFilePicker and the matching WidgetDataView
accessors so a plugin can turn a button into a native "save as" chooser.
The chosen path is delivered through the existing onFileSelected handler,
so no new event type or typed handler is required. This is a
backward-compatible API addition, so bump the SDK to 0.13.0 and bring
recipe.yaml back in sync with the other version sources.

Contents:
- setSaveFilePicker(name, text, filter, title, default_suffix) -> "save_file_picker" action
- WidgetDataView: isSaveFilePicker / saveFilePickerFilter / Title / DefaultSuffix
- version 0.13.0 in conanfile.py, CMakeLists.txt, recipe.yaml + docstring example
- docs: dialog-sdk-reference.md and dialog-plugin-guide.md

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Pablo Iñigo Blasco <pablo.inigo@ibrobotics.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant